package edu.nus.mtech.sem1.ca;

import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import edu.nus.mtech.sem1.ca.data.Database;
import edu.nus.mtech.sem1.ca.data.DatabaseLoader;
import edu.nus.mtech.sem1.ca.main.dao.TelephonyApplicationDao;
import edu.nus.mtech.sem1.ca.plan.Plan;
import edu.nus.mtech.sem1.ca.plan.PlanType;
import edu.nus.mtech.sem1.ca.plan.valueadd.ValueAddedService;
import edu.nus.mtech.sem1.ca.plan.valueadd.ValueAddedType;
import edu.nus.mtech.sem1.ca.txn.CallType;
import edu.nus.mtech.sem1.ca.txn.Transaction;

//
//
//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : Untitled
//  @ File Name : BillGeneratord.java
//  @ Date : 3/19/2011
//  @ Author :


//Lai Oi Lye
//




public class BillGenerator {
	
	private static final float GST = 0.07f;
	private TelephonyApplicationDao databaseDao;
	
	private PlanType planType = null;
	private Set<ValueAddedService> valueAddedType = null;
	private String lineNumber="";
	private float callDuration =0;
	private int channelNos=0;
	
	//Voice charges
	//Voice Subscription
	private float voiceLine =0.0f;
	private float voiceCallTransfer=0;
	//Voice Usage
	private float voiceLocalCalls=0; 	
	private float voiceIDDCalls=0;
	
	//Mobile Charges
	//Mobile Subscription
	private float mobileLine=0;
	private float mobileRoaming =0;
	private float mobileData=0;
	//Mobile Usage
	private float mobileLocalCalls=0;
	private float mobileIDDCalls =0; 
	private float mobileRoamingCalls=0;
	
	//Cable Charges
	private float cableSubscription=0;
	private float channelCharge =0;
	
	private float totalVoiceCharge = 0;
	private float totalMobileCharge = 0;
	private float totalCableCharge = 0;
	
	//totalCurrentCharges = voiceSubscription + mobileSubscription + voiceUsage + mobileUsage + cableSubscription + channelCharge
	private float totalCurrentCharges=0;
	private float previousBal =0;
	private float payment=0;
	private float dueAmt=0;
	
	private Voice voice = new Voice(callDuration);
	private Mobile mobile = new Mobile(callDuration);
	private Plan cable = new Cable();

	private IDD idd = new IDD(planType, callDuration);
	private Roaming roaming = new Roaming(callDuration);
	private CallTransfer callTransfer = new CallTransfer();
	private Data data = new Data();
	private  Channel channel = new Channel(channelNos);
	
	
	
	public BillGenerator(){
		databaseDao=new TelephonyApplicationDao();
		
	}
	public void getBill(Plan plan, Date startDate, Date endDate){
		this.planType= plan.getPlanType();
		this.valueAddedType = plan.getValueAddedServices();
		this.lineNumber = plan.getTelephoneNumber(); 
		
		Calendar planStartDate = Calendar.getInstance();
    	Calendar planEndDate = Calendar.getInstance();
    	planStartDate.setTime(plan.getDateCommenced());
    	if(plan.getDateTerminated()==null){//Zaw modified for active plan
    		planEndDate.setTime(new Date());
    	}
    	else
    		planEndDate.setTime(plan.getDateTerminated());

		
				
		//Compute payment details
		
		//Compute Voice Charges
    	if (planType== PlanType.VOICE){
    		//compute Voice Subscription

    		if((!(planEndDate.getTime().before(startDate))&&(!(planStartDate.getTime().after(endDate))))){
    			setVoiceLine(voice.getSubscriptionCharge());
    			//local call charges

    			callDuration = getCallDuration(CallType.LOCAL, startDate, endDate);
    			setCallDuration(callDuration);
    			if(callDuration != 0){
    				voice.setCallDuration(callDuration);
    				setVoiceLocalCalls(voice.getCharge());


    			}



    			//get the valueAdded services
    			Iterator<ValueAddedService> v = valueAddedType.iterator();
    			ValueAddedService valueType = new ValueAddedService();
    			while(v.hasNext()){
    				valueType = v.next();
    				java.util.Date dteTerminated= null;
    				if(valueType.getDateTerminated()==null)
    					dteTerminated=new Date();
    				else
    					dteTerminated=valueType.getDateTerminated();
    				
    				if((!(dteTerminated.before(startDate))&&(!(valueType.getDateCommenced().after(endDate))))){
    					if(valueType.getValueAddedType()== ValueAddedType.CALLXFER){
    						setVoiceCallTransfer(callTransfer.getSubscriptionCharge());

    					}
    					//Usage
    					if(valueType.getValueAddedType()== ValueAddedType.IDD){ // Voice IDD Call Charges
    						callDuration = getCallDuration(CallType.IDD, startDate, endDate);
    						setCallDuration(callDuration);
    						if(callDuration != 0){
    							idd.setCallDuration(callDuration);
    							setVoiceIDDCalls(idd.getCharge());

    						}

    					}
    				}
    			}
    		}

    	}

    	//Compute Mobile Charges
    	if (planType== PlanType.MOBILE){

    		if((!(planEndDate.getTime().before(startDate))&&(!(planStartDate.getTime().after(endDate))))){
    			setMobileLine(mobile.getSubscriptionCharge());//Mobile Subscription
    			//compute Mobile Local Charge
    			callDuration = getCallDuration(CallType.LOCAL, startDate, endDate);


    			setCallDuration(callDuration);
    			if(callDuration != 0){				
    				mobile.setCallDuration(callDuration);
    				setMobileLocalCalls(mobile.getCharge());

    			}	

    			//get the valueAdded services
    			Iterator<ValueAddedService> v = valueAddedType.iterator();
    			ValueAddedService valueType = new ValueAddedService();
    			while(v.hasNext()){
    				valueType = v.next();
    				java.util.Date dteTerminated= null;
    				if(valueType.getDateTerminated()==null)
    					dteTerminated=new Date();
    				else
    					dteTerminated=valueType.getDateTerminated();
    				if((!(dteTerminated.before(startDate))&&(!(valueType.getDateCommenced().after(endDate))))){
    					if(valueType.getValueAddedType()== ValueAddedType.ROAMING){ //Mobile_Roaming
    						setMobileRoaming(roaming.getSubscriptionCharge());// get Roaming subscription

    						// get Roamimg usage
    						callDuration = getCallDuration(CallType.ROAMING, startDate, endDate);
    						setCallDuration(callDuration);
    						if(callDuration != 0){
    							roaming.setCallDuration(callDuration);
    							setMobileRoamingCalls(roaming.getCharge());
    						}

    					}
    					if(valueType.getValueAddedType()== ValueAddedType.DATA){
    						setMobileData(data.getSubscriptionCharge());
    					}			
    					//Compute Usage
    					//Compute Mobile IDD
    					if(valueType.getValueAddedType()== ValueAddedType.IDD){	//Mobile_IDD	
    						callDuration = getCallDuration(CallType.IDD, startDate, endDate);
    						setCallDuration(callDuration);
    						if(callDuration != 0){
    							idd.setCallDuration(callDuration);
    							setMobileIDDCalls(idd.getCharge());
    						}
    					}
    				}
    			}
    		}
    	}

    	//Compute Cable Charges
    	if(planType == PlanType.CABLE){
    		if((!(planEndDate.getTime().before(startDate))&&(!(planStartDate.getTime().after(endDate))))){
    			setCableSubscription(cable.getSubscriptionCharge());
    			//get the valueAdded services
    			Iterator<ValueAddedService> v = valueAddedType.iterator();
    			ValueAddedService valueType = new ValueAddedService();
    			while(v.hasNext()){
    				valueType = v.next();
    				java.util.Date dteTerminated= null;
    				if(valueType.getDateTerminated()==null)
    					dteTerminated=new Date();
    				else
    					dteTerminated=valueType.getDateTerminated();
    				if((!(dteTerminated.before(startDate))&&(!(valueType.getDateCommenced().after(endDate))))){
    					if(valueType.getValueAddedType()== ValueAddedType.CHANNEL){ //Check channel added

    						// get Roamimg usage
    						channelNos = Integer.parseInt(valueType.getAdditionalChannels());
    						System.out.println("Channel Nos ....." + channelNos);

    						setChannelNos(channelNos);

    						if(channelNos!=0){
    							channel.setChannelNos(channelNos);
    							setChannelCharge(channel.getCharge());
    						}

    					}
    				}
    			}
    		}
    	}

	}

	
	public float getCallDuration(CallType callType, Date startDate, Date endDate) {
		float duration =0;
		Transaction tx = new Transaction();
		
		Set<Transaction> transactionSet =new TreeSet<Transaction>();
		Map<String, Set<Transaction>> transactionMap = databaseDao.getTransactionData();
		if(transactionMap.containsKey(lineNumber)){
			transactionSet = transactionMap.get(lineNumber);
			Iterator<Transaction> it=transactionSet.iterator();
			tx.setLineNumber(lineNumber);
			
			while(it.hasNext())
	        {
	           tx= it.next();
	          
	          if(tx.getCallType()== callType){
	        	  Date callDate = tx.getDateOfCall();
	        	
	           	  if((callDate.after(startDate)&& (callDate.before(endDate)))){
	          
	           		  duration += tx.getDurationOfCall();	   
	      
	           	  }
	        	  
	          }
	         
	        }
		}
				
		return duration;
	}
	public void setCallDuration(float callDuration) {
		this.callDuration = callDuration;
	}
	

	public float getVoiceLine() {
		
		return voiceLine;
	}


	public void setVoiceLine(float voiceLine) {
		this.voiceLine = voiceLine;
	}


	public float getVoiceCallTransfer() {
		
		return voiceCallTransfer;
	}


	public void setVoiceCallTransfer(float voiceCallTransfer) {
		this.voiceCallTransfer = voiceCallTransfer;
	}


	public float getVoiceLocalCalls() {
		
		return voiceLocalCalls;
	}


	public void setVoiceLocalCalls(float voiceLocalCalls) {
		this.voiceLocalCalls = voiceLocalCalls;
	}


	public float getVoiceIDDCalls() {
		
		return voiceIDDCalls;
	}


	public void setVoiceIDDCalls(float voiceIDDCalls) {
		this.voiceIDDCalls = voiceIDDCalls;
	}


	public float getMobileLine() {
		
		return mobileLine;
	}


	public void setMobileLine(float mobileLine) {
		this.mobileLine = mobileLine;
	}


	public float getMobileRoaming() {
		
		return mobileRoaming;
	}


	public void setMobileRoaming(float mobileRoaming) {
		this.mobileRoaming = mobileRoaming;
	}


	public float getMobileData() {
		
		return mobileData;
	}


	public void setMobileData(float mobileData) {
		this.mobileData = mobileData;
	}


	public float getMobileLocalCalls() {
		
		return mobileLocalCalls;
	}


	public void setMobileLocalCalls(float mobileLocalCalls) {
		this.mobileLocalCalls = mobileLocalCalls;
	}


	public float getMobileIDDCalls() {
		
		return mobileIDDCalls;
	}


	public void setMobileIDDCalls(float mobileIDDCalls) {
		this.mobileIDDCalls = mobileIDDCalls;
	}


	public float getMobileRoamingCalls() {
		
		return mobileRoamingCalls;
	}


	public void setMobileRoamingCalls(float mobileRoamingCalls) {
		this.mobileRoamingCalls = mobileRoamingCalls;
	}


	public float getCableSubscription() {
		
		return cableSubscription;
	}


	public void setCableSubscription(float cableSubscription) {
		this.cableSubscription = cableSubscription;
	}


	public float getChannelCharge() {
			
		return channelCharge;
	}


	public void setChannelCharge(float channelCharge) {
		this.channelCharge = channelCharge;
	}


	public float getVoiceSubscription() {
		float linecharge = getVoiceLine();
		
		float callTxf = getVoiceCallTransfer();
		float subscription = linecharge + callTxf;
		
		return subscription;
	}


	public void setVoiceSubscription(float voiceSubscription) {
	}


	public float getMobileSubscription() {
		float linecharge = getMobileLine();
		float roaming = getMobileRoaming();
		float data = getMobileData();
		float subscription = linecharge + roaming + data;
		return subscription;
	}


	public void setMobileSubscription(float mobileSubscription) {
	}


	public float getVoiceUsage() {
		float localCalls = getVoiceLocalCalls();
		float iddCalls = getVoiceIDDCalls();
		float usage = localCalls + iddCalls;
		
		return usage;
	}


	public void setVoiceUsage(float voiceUsage) {
	}


	public float getMobileUsage() {
		float localCalls = getMobileLocalCalls();
		float mobileCalls = getMobileIDDCalls();
		float roamingCalls = getMobileRoamingCalls();
		float usage = localCalls + mobileCalls + roamingCalls;
		return usage;
	}


	public void setMobileUsage(float mobileUsage) {
	}


	public float getTotalVoiceCharge() {
		totalVoiceCharge = getVoiceSubscription()+ getVoiceUsage();
		return totalVoiceCharge;
	}
	public void setTotalVoiceCharge(float totalVoiceCharge) {
		this.totalVoiceCharge = totalVoiceCharge;
	}
	public float getTotalMobileCharge() {
		totalMobileCharge = getMobileSubscription()+ getMobileUsage();
		return totalMobileCharge;
	}
	public void setTotalMobileCharge(float totalMobileCharge) {
		this.totalMobileCharge = totalMobileCharge;
	}
	public float getTotalCableCharge() {
		totalCableCharge = getCableSubscription()+ getChannelCharge();
		return totalCableCharge;
	}
	public void setTotalCableCharge(float totalCableCharge) {
		this.totalCableCharge = totalCableCharge;
	}
	public float getTotalCurrentCharges() {
		totalCurrentCharges = getCurrentCharge() + getGstCharge();
		
		
		return totalCurrentCharges;
	}


	public void setTotalCurrentCharges(float totalCurrentCharges) {
		this.totalCurrentCharges = totalCurrentCharges;
	}

	
	public float getCurrentCharge() {
		float voiceSubscription = getVoiceSubscription();
		float mobileSubscription = getMobileSubscription();
		float voiceUsage = getVoiceUsage();
		float mobileUsage = getMobileUsage();
		float cableSubscription = getCableSubscription();
		float channelCharge = getChannelCharge();
		float currentCharge = voiceSubscription + mobileSubscription + 
					voiceUsage + mobileUsage + cableSubscription + channelCharge;
		return currentCharge;
	}
	public void setCurrentCharge(float currentCharge) {
	}
	public float getGstCharge() {
		
		float gstcharge = getCurrentCharge() * GST;
		
		return gstcharge;
	}


	public void setGstCharge(float gstCharge) {
	}


	public float getPreviousBal() {
		return previousBal;
	}


	public void setPreviousBal(float previousBal) {
		this.previousBal = previousBal;
	}


	public float getPayment() {
		return payment;
	}


	public void setPayment(float payment) {
		this.payment = payment;
	}


	public float getDueAmt() {
		return dueAmt;
	}


	public void setDueAmt(float dueAmt) {
		this.dueAmt = dueAmt;
	}
	public int getChannelNos() {
		return channelNos;
	}
	public void setChannelNos(int channelNos) {
		this.channelNos = channelNos;
	}
	
	
	
		
		
	
}
